package com.github.zhijieqing.socket.cluster.redis;

import com.github.zhijieqing.common.web.utils.RedisUtils;
import com.github.zhijieqing.socket.cluster.common.config.Const;
import com.github.zhijieqing.socket.cluster.common.node.SocketServerNode;
import com.github.zhijieqing.socket.cluster.common.storage.ClientStorage;
import com.github.zhijieqing.socket.cluster.common.storage.SessionClientStorage;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;

import javax.websocket.Session;
import java.util.Collection;
import java.util.Set;

@Slf4j
public class RedisClientStorage extends SessionClientStorage {
    @Setter
    private RedissonClient redissonClient;

    @Override
    public void put(SocketServerNode socketServerNode) {
        redissonClient.getMap(RedisUtils.getKey(Const.NODE_KEY_PREFIX)).put(socketServerNode.getId(), socketServerNode);
    }

    @Override
    public void remove(SocketServerNode socketServerNode) {
        /*移除serverNode则同时移除clientId下的对应serverNode*/
        getSessionClientCache().values().forEach(clientIdSet -> {
            clientIdSet.forEach(clientId -> {
                try {
                    remove(clientId, socketServerNode);
                } catch (Exception e) {
                    log.error("移除节点[{}]时移除Client[{}]失败", socketServerNode.getId(), clientId, e);
                }
            });
        });
        redissonClient.getMap(RedisUtils.getKey(Const.NODE_KEY_PREFIX)).remove(socketServerNode.getId());
    }

    private String getClientKey(String clientId) {
        return RedisUtils.getKey(Const.CLIENT_KEY_PREFIX + clientId);
    }

    private RMap<String, SocketServerNode> getBucket(String clientId) {
        return redissonClient.getMap(getClientKey(clientId));
    }

    @Override
    public void put(String clientId, Session session, SocketServerNode socketServerNode) {
        super.put(clientId, session);
        put(clientId, session.getId(), socketServerNode);
    }

    @Override
    public void put(String clientId, String sessionId,SocketServerNode socketServerNode) {
        put(clientId,sessionId);
        getBucket(clientId).put(socketServerNode.getId(), socketServerNode);
    }

    @Override
    public boolean contains(String clientId) {
        return getBucket(clientId).isExists();
    }

    @Override
    public void remove(String clientId) {
        redissonClient.getBucket(getClientKey(clientId)).delete();
    }

    @Override
    public void remove(String clientId, SocketServerNode socketServerNode) {
        getBucket(clientId).remove(socketServerNode.getId());
    }

    @Override
    public void remove(String clientId, Session session, SocketServerNode socketServerNode) {
        super.remove(clientId, session);
        if(getSessionIdSet(clientId).isEmpty()){
            remove(clientId, socketServerNode);
        }
    }

    @Override
    public SocketServerNode getOne(String clientId) {
        return getBucket(clientId).get(0);
    }

    @Override
    public Collection<SocketServerNode> get(String clientId) {
        return getBucket(clientId).values();
    }

    @Override
    public boolean currentNodeContains(String clientId, SocketServerNode currentServerNode) {
        boolean result = super.currentNodeContains(clientId,currentServerNode);
        if(!result){
            result = getBucket(clientId).containsKey(currentServerNode.getId());
        }
        return result;
    }
}
